dojo.provide('app.mvc.View');

dojo.declare('app.mvc.View', [], {
	_dataCtor : null,
	_props : null,
	_map : null,
	_deferredData : null,
	properties : {},
	constructor : function(bag) {
		console.group('Building');
		this.properties = bag || this.properties;
		this._map = {};
		this._deferredData = {};
		console.log(this.properties);
		var proto = {};

		var _self = this;
		for (p in this.properties) {
			console.log(p);
			console.log(this.properties[p]);
			proto[p] = null;
			var aux = this.properties[p] || {};
			var id = aux.id || p;
			var name = aux.name || p;
			var getter = aux.getter || function(id) {
				console.group('Get Deferred');
				console.log(arguments);
				console.groupEnd();
				return _self._deferredData[id];
			};
			var setter = aux.setter || function(id, value, reset) {
				console.group('Set Deferred');
				console.log(arguments);
				if (reset == true) {
					_self._deferredData[id] = null;
				} else {
					_self._deferredData[id] = value;
				}
				console.groupEnd();
			};
			this._bind(name, id, getter, setter);
		}
		this._props = proto;
		this._dataCtor = function() {
		};
		this._dataCtor.prototype = proto;
		console.groupEnd();

	},
	bind : function(bag) {
		console.log('bind');
		console.log(bag);
		if (!bag)
			return;
		var name, _setter, _getter, _id = "";
		var o;
		function _setWdg(id, val, reset) {
			console.group('Set Widget');
			console.log(arguments);
			var wdg = dijit.byId(id);
			if (reset == true && wdg.reset) {
				wdg.reset();
			} else {
				wdg.set('value', val);
			}
			console.groupEnd();
		}
		function _getWdg(id) {
			console.group('Get Widget');
			console.log(arguments);
			console.groupEnd();
			return dijit.byId(id).get('value');

		}
		function _setNode(id, val, reset) {
			console.group('Set Node');
			console.log(arguments);
			dojo.attr(id, 'value', val);
			console.groupEnd();
		}
		function _getNode(id) {
			console.group('Get Node');
			console.log(arguments);
			console.groupEnd();
			return dojo.attr(id, 'value');
		}

		name = bag.name;
		_setter = bag.setter;
		_getter = bag.getter;

		if (bag.widget) {
			var wdg = dijit.byId(bag.widget);
			if (name)
				wdg.set('name', name);
			else
				name = wdg.get('name');
			_id = wdg.get('id');
			_setter = _setter || _setWdg;
			_getter = _getter || _getWdg;
		}

		if (bag.node) {
			if (name)
				dojo.attr(bag.node, 'name', name);
			else
				name = dojo.attr(bag.node, 'name');
			_id = dojo.attr(bag.node, 'id');
			_setter = _setter || _setNode;
			_getter = _getter || _getNode;
		}
		if (bag.id && _setter && _getter) {
			_id = bag.id;
		}
		console.log(name);
		console.log(name in this._props);
		if (name in this._props) {
			this._bind(name, _id, _getter, _setter)
			if (this._deferredData[name]) {
				console.log('Setting ' + name);
				_setter(_id, this._deferredData[name]);
			}
		} else {
			throw 'Unable to bind property using name and id attributes:'
					+ name + ', ' + _id;
		}
	},
	_bind : function(name, id, getter, setter) {
		this._map[name] = {
			id : id,
			getter : function() {
				return getter(id);
			},
			setter : function(val) {
				setter(id, val);
			}
		};
	},
	set : function(p, value, resetEmpty) {
		console.log('set');
		console.log(arguments);
		if (!p)
			return;
		var props;
		if (typeof p == 'string') {
			props = {};
			props[p] = value;
		} else {
			props = p;
			resetEmpty = value;
		}
		var ret = {};
		var empty = new this._dataCtor();
		for (prop in props) {
			if (prop in this._map && props[prop] !== null) {
				console.log('Setting ' + prop);
				this._deferredData[prop] = props[prop];
				this._map[prop].setter.call(this,props[prop]);
				ret[prop] = props[prop];
				empty[prop] = true;
				console.log(this._map[prop]);
				console.log(this._deferredData[prop]);
			}
		}
		if (resetEmpty == true) {
			for (prop in empty) {
				if (!empty[prop]) {
					console.log('Resetting ' + prop);
					this._deferredData[prop] = null;
					this._map[prop].setter.call(this, null, true);
				}
			}
		}
		return ret;
	},
	get : function(prop) {
		var props;
		if (typeof prop == 'string') {
			props = {};
			props[prop] = null;
		} else {
			props = prop;
		}
		var ret = null;
		for (pr in props) {
			if (pr in this._map) {
				ret = ret || {};
				ret[pr] = this._map[pr].getter.call(this);
			}
		}
		return ret;
	},
	data : function(filter) {
		var flt = filter || this._props;
		var ret = new this._dataCtor();
		for (p in flt) {
			if (p in this._map) {
				ret[p] = this._map[p].getter.call(this);
			}
		}
		return ret;
	}
});
app.mvc.View.register = function(prop, view) {
	console.group('app.mvc.View.register');
	console.log(arguments);
	var views = {};
	if (typeof prop == "string") {
		views[prop] = view;
	} else {
		views = prop;
	}
	for (id in views) {
		console.log('registering ' + id);
		app.mvc.View._reg[id] = views[id];
	}
	console.groupEnd();
};
app.mvc.View._reg = {};
app.mvc.View.get = function(id) {
	return app.mvc.View._reg[id];
};